package com.proxy;

import com.Async.Callback;
import com.Async.RpcFuture;
import com.client.ClientTerminal;
import com.serializetool.Request;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;

public class ProxyService implements InvocationHandler {
    Object interface0;
    AOP aop;
    boolean async;
    private static HashMap<Class,String> map = new HashMap<>();
    static{
        map.put(Integer.class,"int");
        map.put(Float.class,"float");
        map.put(Double.class,"double");
        map.put(Long.class,"long");
        map.put(Byte.class,"byte");
        map.put(String.class,"string");
        map.put(Boolean.class,"boolean");
    }
    public ProxyService(Object o,boolean async){
        interface0 = o;
        aop = new AOPImpl();
        this.async = async;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Request request = new Request();
        request.setClassName(interface0.getClass().getName());
        request.setMethodName(method.getName());
        int paramlen = args.length;
        String[] paramTypes = new String[paramlen];
        for(int i=0;i<paramlen;i++){
            paramTypes[i] = map.get(args[i].getClass());
            if(paramTypes[i]==null) throw new Exception("RPC不支持该参数");
        }
        request.setParameterTypes(paramTypes);
        request.setParameters(args);
        aop.before();
        RpcFuture future = (RpcFuture) ClientTerminal.getClientTerminal().remoteCall(request, true
                , new Callback() {
                    @Override
                    public void onSuccess(Object param) {
                        System.out.println("\n成功时回调:" + param);
                    }

                    @Override
                    public void onFailure(Throwable error) {

                        System.out.println("\n失败时回调:" + error.getStackTrace());
                    }
                }
                , nameToServiceName(interface0.getClass().getPackageName(),method.getName()));
        aop.after();
        if(async) return null;
        return future.get();
    }

    public Object createProxy(){
        return Proxy.newProxyInstance(interface0.getClass().getClassLoader(),
                interface0.getClass().getInterfaces(), this);
    }

    /**
     *
     * @param str1 包名
     * @param str2 方法名
     * @return 获得包名/方法名，包名中间的.全部换作了/
     * 如com.service.ServiceImpl#printString()，会返回com/service/ServiceImpl/printString
     */
    private String nameToServiceName(String str1,String str2){
        char[] c = str1.toCharArray();
        int len = c.length;
        for(int i=0;i<len;i++){
            if(c[i]=='.') c[i] = '/';
        }
        StringBuilder builder = new StringBuilder("/");
        builder.append(c);
        builder.append("/");
        builder.append(str2);
        return builder.toString();
    }
}
